package com.csap.framework.oauth2.server.service.impl;

import cn.dev33.satoken.LoginUtil;
import com.csap.framework.annotation.apidoc.Description;
import com.csap.framework.oauth2.UserInfo;
import com.csap.framework.oauth2.server.entity.UserInfoEntity;
import com.csap.framework.oauth2.server.model.UserInfoModel;
import com.csap.framework.oauth2.server.mybatis.UserInfoMapper;
import com.csap.framework.oauth2.server.service.RolesService;
import com.csap.framework.oauth2.server.service.UserAttributeService;
import com.csap.framework.oauth2.server.service.UserInfoService;
import com.csap.framework.oauth2.server.service.UserPermissionsService;
import com.csap.framework.oauth2.server.service.UserRolesService;
import com.csap.framework.redis.RedisUtil;
import com.csap.mybatisplus.extension.service.impl.BaseCsapServiceImpl;
import com.google.common.collect.Lists;
import lombok.Getter;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户信息表
 * </p>
 *
 * @author yangchengfu
 * @dateTime 2021-07-25 23:51:30
 */
@Service
@Description(value = "用户信息表ServiceImpl")
public class UserInfoServiceImpl extends BaseCsapServiceImpl<UserInfoMapper, UserInfoEntity, UserInfoModel, String> implements UserInfoService {
    @Resource
    private UserRolesService userRolesService;
    @Resource
    private UserAttributeService userAttributeService;
    @Getter
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RolesService rolesService;
    @Resource
    private UserPermissionsService permissionsService;

    @Override
    public UserInfo userInfo(Object loginId, Long time, Boolean clear) {
        if (clear) {
            redisUtil.hdel(LoginUtil.getInstance().cachekey(loginId), USERINFO);
        }
        return getStore(LoginUtil.getInstance().cachekey(loginId), USERINFO, () ->
                lambdaQuery()
                        .select(UserInfoEntity::getUserId, UserInfoEntity::getUserName,
                                UserInfoEntity::getEmail, UserInfoEntity::getNickName,
                                UserInfoEntity::getAvatar, UserInfoEntity::getMobile,
                                UserInfoEntity::getSex, UserInfoEntity::getAge)
                        .eq(UserInfoEntity::getUserId, loginId)
                        .oneOptional()
                        .transform(UserInfo.class), time);
    }

    @Override
    public List<Long> roleList(String userId, Long time, Boolean clear) {
        if (clear) {
            redisUtil.hdel(LoginUtil.getInstance().cachekey(userId), ROLE);
        }
        return getStore(LoginUtil.getInstance().cachekey(userId), ROLE, () ->
                userRolesService.roleList(userId), time);
    }

    @Override
    public void rolePermissions(String userId, UserInfo userInfo, Long time) {
        List<Long> longs = roleList(userId, time, Boolean.FALSE);
        Set<String> strings = longs.stream().map(String::valueOf).collect(Collectors.toSet());
        userInfo.setRoleIds(longs);
        userInfo.setRoleList(rolesService.getRole(strings));
        Set<String> pre = rolesService.getRolePremissions(strings);
        pre.addAll(permissionsService.permissions(userId));
        userInfo.setPermissionsList(Lists.newArrayList(pre));
    }

    @Override
    public Map<String, List<String>> userAttribute(String userId, Long time, Boolean clear) {
        if (clear) {
            redisUtil.hdel(LoginUtil.getInstance().cachekey(userId), USER_ATTRIBUTE);
        }
        return getStore(LoginUtil.getInstance().cachekey(userId), USER_ATTRIBUTE, () ->
                userAttributeService.userAttribute(userId), time);
    }

    @Override
    public List<String> permissionsList(String userId, Long time, Boolean clear) {
        if (clear) {
            redisUtil.hdel(LoginUtil.getInstance().cachekey(userId), PERMISSIONS);
        }
        return getStore(LoginUtil.getInstance().cachekey(userId), PERMISSIONS, () ->
                userRolesService.permissionsList(userId), time);
    }

    @Override
    public boolean update(UserInfoModel t) {
        return super.update(t);
    }
}
